/*
 *  Author: Samuel Abels <spam debain org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include "gui_subnet_calculator.h"

//#define _DEBUG_


/******************************************************************************
 * Constructor/Destructor
 ******************************************************************************/
GUISubnetCalculator::GUISubnetCalculator()
: label_range(_("Address Range:")),
  label_dash("-")
{
  resize(2, 4);
  set_border_width(6);
  set_row_spacings(6);
  set_col_spacings(12);
  spin_from.set_numeric(FALSE);
  spin_from.set_range(0, (double)pow((double)2, 32) - 1);
  spin_from.set_increments(1, 256);
  spin_from.set_wrap();
  spin_to.set_numeric(FALSE);
  spin_to.set_range(0, (double)pow((double)2, 32) - 1);
  spin_to.set_increments(1, 256);
  spin_to.set_wrap();
  scrolled.add(prefixlist);
  scrolled.set_shadow_type(SHADOW_IN);
  scrolled.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC);
  attach(label_range, 0, 1, 0, 1, FILL,        FILL);
  attach(spin_from,   1, 2, 0, 1, FILL|EXPAND, FILL);
  attach(label_dash,  2, 3, 0, 1, FILL,        FILL);
  attach(spin_to,     3, 4, 0, 1, FILL|EXPAND, FILL);
  attach(scrolled,    0, 4, 1, 2, FILL|EXPAND, FILL|EXPAND);
  spin_from.signal_input().connect(
            SigC::bind(SigC::slot(*this, &GUISubnetCalculator::map_ip_input),
                       &spin_from));
  spin_from.signal_output().connect(
            SigC::bind(SigC::slot(*this, &GUISubnetCalculator::map_ip_output),
                       &spin_from));
  spin_from.signal_value_changed().connect(
            SigC::slot(*this, &GUISubnetCalculator::on_range_changed));
  spin_to.signal_input().connect(
            SigC::bind(SigC::slot(*this, &GUISubnetCalculator::map_ip_input),
                       &spin_to));
  spin_to.signal_output().connect(
            SigC::bind(SigC::slot(*this, &GUISubnetCalculator::map_ip_output),
                       &spin_to));
  spin_to.signal_value_changed().connect(
            SigC::slot(*this, &GUISubnetCalculator::on_range_changed));
}


GUISubnetCalculator::~GUISubnetCalculator()
{
}


/******************************************************************************
 * Public
 ******************************************************************************/
/* Switch event emissions off. */
void GUISubnetCalculator::lock_signals(void)
{
  lock_events = TRUE;
}


/* Switch event emissions on. */
void GUISubnetCalculator::unlock_signals(void)
{
  lock_events = FALSE;
}


/* Switch event emissions on. */
void GUISubnetCalculator::set_range(unsigned int from, unsigned int to)
{
  spin_from.set_value(from);
  spin_to.set_value(to);
}


/******************************************************************************
 * Protected
 ******************************************************************************/
int GUISubnetCalculator::map_ip_input(double* value, SpinButton* spin)
{
#ifdef _DEBUG_EXCESSIVE_
  printf("GUISubnetCalculator::map_ip_input(): Called.\n");
#endif
  string       ip     = spin->get_text();
  unsigned int ip_int = 0;
  if (ipv4_ip2integer(ip.c_str(), &ip_int) < 0)
    return 0;
#ifdef _DEBUG_EXCESSIVE_
  printf("GUISubnetCalculator::map_ip_input(): Value: %s, %i\n", ip.c_str(),
                                                                 ip_int);
#endif
  *value = (double)ip_int;
  return 1;
}


bool GUISubnetCalculator::map_ip_output(SpinButton* spin)
{
#ifdef _DEBUG_EXCESSIVE_
  printf("GUISubnetCalculator::map_ip_output(): Called.\n");
#endif
  char         ip[36] = "";
  unsigned int ip_int = (unsigned int)spin->get_adjustment()->get_value();
#ifdef _DEBUG_EXCESSIVE_
  printf("GUISubnetCalculator::map_ip_output(): Double: %d\n",
         spin->get_adjustment()->get_value());
#endif
  ipv4_integer2ip(ip_int, ip);
  spin->set_text(ip);
  return TRUE;
}


void GUISubnetCalculator::on_range_changed(void)
{
#ifdef _DEBUG_
  printf("GUISubnetCalculator::on_range_changed(): Called.\n");
#endif
  if (lock_events)
    return;
  unsigned int from = (unsigned int)spin_from.get_value();
  unsigned int to   = (unsigned int)spin_to.get_value();
  signal_range_changed.emit(from, to);
}
